use std::collections::HashMap;

use serde::{Deserialize, Serialize};

use crate::database::{ConnectorProtocol, DataSource, DatabaseType};

#[derive(Debug, Default, Serialize, Deserialize, Clone, PartialEq)]
pub enum StorageType {
    #[default]
    #[serde(rename = "mysql")]
    MySQL,
    #[serde(rename = "sqlite")]
    SQLite,
    #[serde(rename = "dgraph")]
    Dgraph,
}

#[derive(Debug, Default, Serialize, Deserialize, Clone, PartialEq)]
pub enum Storage {
    #[default]
    #[serde(rename = "empty")]
    Empty,
    #[serde(rename = "mysql")]
    MySQL(MySQLStorageOption),
    #[serde(rename = "sqlite")]
    SQLite(SQLiteStorageOption),
}

#[derive(Debug, Default, Serialize, Deserialize, Clone, PartialEq)]
pub struct MySQLStorageOption {
    pub url: String,
    pub username: Option<String>,
    pub password: Option<String>,
    pub options: Option<HashMap<String, String>>,
}

#[derive(Debug, Default, Serialize, Deserialize, Clone, PartialEq)]
pub struct SQLiteStorageOption {
    pub url: String,
    pub username: Option<String>,
    pub password: Option<String>,
    pub options: Option<HashMap<String, String>>,
}

impl Storage {
    pub fn new(storage_type: &StorageType, options: &String) -> anyhow::Result<Self> {
        match storage_type {
            StorageType::MySQL => {
                let op: MySQLStorageOption = serde_json::from_str(options)
                    .map_err(|err| anyhow::anyhow!("[{}]{}", options, err))?;

                Ok(Self::MySQL(op))
            }
            StorageType::SQLite => {
                let op: SQLiteStorageOption = serde_json::from_str(options)
                    .map_err(|err| anyhow::anyhow!("[{}]{}", options, err))?;

                Ok(Self::SQLite(op))
            }
            _ => Err(anyhow::anyhow!("不支持的存储类型:{:?}", storage_type)),
        }
    }
}

impl Storage {
    pub fn get_connector_datasource(&self) -> anyhow::Result<DataSource> {
        match self {
            Self::MySQL(v) => Ok(DataSource {
                id: 0,
                database_type: DatabaseType::MySQL,
                protocol: ConnectorProtocol::MySQL,
                url: v.url.clone(),
                username: v.username.clone(),
                password: v.password.clone(),
                options: v.options.clone(),
            }),
            Self::SQLite(v) => Ok(DataSource {
                id: 0,
                database_type: DatabaseType::SQLite,
                protocol: ConnectorProtocol::SQLite,
                url: v.url.clone(),
                username: v.username.clone(),
                password: v.password.clone(),
                options: v.options.clone(),
            }),
            _ => Err(anyhow::anyhow!("")),
        }
    }
}
